package com.vo;

import java.io.Serializable;
import java.text.DateFormat;
import java.util.*;

/**
 * Classe Contato utilizada como Variable Object.
 * @author Jean Vasconcelos, Carla Sukeyosi, Matheus Emanuel, Heitor Carvalho
 */
public class Contact implements Serializable
{
    private String name;
    private String address;
    private Calendar dateOfBirth;
    private String comments;
    private List<Event> events;
    private List<ContactWays> contactWays;
    private String imagePath;
    private List<Integer> groups;
    
    /**
     * Cria um Contato a patir do nome, endereco e data de nascimento.
     */
    public Contact(String name, String address, Calendar dateOfBirth)
    {
        this.name = name;
        this.address = address;
        this.dateOfBirth = dateOfBirth;
        this.events = new ArrayList<Event>();
        this.contactWays = new ArrayList<ContactWays>();
        this.groups = new ArrayList<Integer>();
    }
    
    /**
     * Recupera as informacoes dos grupos ao qual o contato pertence
     * @return lista de inteiros representando os grupos
     */
    public List<Integer> getGroups() 
    {
        return groups;
    }
    
    /**
     * Adiciona um novo grupo ao contato
     * @param group inteiro representando o grupo a ser adicionado
     */
    public boolean addGroup(Integer group) 
    {
        return this.groups.add(group);
    }
    
    /**
     * Recupera o caminho para a imagem do contato
     * @return caminho para imagem do contato
     */
    public String getImagePath() 
    {
        return imagePath;
    }
    
    /**
     * Altera o caminho para a imagem do contato
     * @param imagePath novo caminho para a imagem
     */
    public void setImagePath(String imagePath) 
    {
        this.imagePath = imagePath;
    }

    /**
     * Retorna o endereco do Contato.
     * @return Endereco do Contato.
     */
    public String getAddress()
    {
        return address;
    }

    /**
     * Modifica o endereco do Contato.
     * @param address Novo endereco do Contato.
     */
    public void setAddress(String address)
    {
        this.address = address;
    }

    /**
     * Recupera a data de nascimento do Contato.
     * @return Data de nascimento do Contato.
     */
    public Calendar getDateOfBirth()
    {
        return dateOfBirth;
    }

    /**
     * Modifica a data de nascimento do Contato.
     * @param dateOfBirth Nova data de nascimento do Contato.
     */
    public void setDateOfBirth(Calendar dateOfBirth)
    {
        this.dateOfBirth = dateOfBirth;
    }

    /**
     * Recupera o comentario sobre Contato.
     * @return Comentario sobre o Contato.
     */
    public String getComments()
    {
        return comments;
    }

    /**
     * Modifica o comentario sobre o Contato.
     * @param comments Novo comentario sobre o Contato.
     */
    public void setComments(String comments)
    {
        this.comments = comments;
    }

    /**
     * Recupera o nome do Contato.
     * @return Nome do Contato.
     */
    public String getName()
    {
        return name;
    }

    /**
     * Modifica o nome do Contato.
     * @param name Novo nome do Contato.
     */
    public void setName(String name)
    {
        this.name = name;
    }

    /**
     * Recupera a lista<formas de contato(ContactWays)> do Contato.
     * @return Formas de contato(ContactWays) do Contato.
     */
    public List<ContactWays> getContactWays()
    {
        return contactWays;
    }
    
    /**
     * Adiciona nova forma de contato(ContactWays) a lista<formas de contato>.
     * @param newContactWay Formas de contato(ContactWays) a ser adicionada.
     * @return true se o elemento foi adicionado.
     */
    public boolean addContactWay(ContactWays newContactWay)
    {
        if (!contactWays.contains(newContactWay))
            return contactWays.add(newContactWay);
        return false;
    }
    
    /**
     * Remove forma de contato(ContactWays) da lista<formas de contato> do Contato.
     * @param contactWay Forma de contato(ContactWays) a ser removida.
     * @return true se o elemento é removido da lista.
     */
    public boolean removeContactWay(ContactWays contactWay)
    {
        return contactWays.remove(contactWay);
    }
    
    /**
     * Adiciona evento(Event) na lista<eventos> do Contato.
     * @param newEvent Evento(Event) a ser adicionado.
     * @return true se o elemento é adicionado na lista.
     */
    public boolean addEvents(Event newEvent)
    {
        if (!events.contains(newEvent))
            return events.add(newEvent) && newEvent.addContact(this);
        return false;
    }
    
    /**
     * Remove evento(Event) da lista<eventos> do Contato.
     * @param event Evento(Event) a ser removido.
     * @return true se o elemento é removido da lista.
     */
    public boolean removeEvents(Event event)
    {
        return events.remove(event);
    }

    /**
     * Recupera a lista<eventos(Event)> do Contato.
     * @return Lista<eventos> do Contato.
     */
    public List<Event> getEvents()
    {
        return events;
    }

    /**
     * Verifica se dois Contatos sao iguais, no caso de possuirem o mesmo nome 
     * e endereço.
     * @param obj Contato a ser comparado.
     * @return true caso os Contatos sejam iguais.
     */
     @Override
    public boolean equals(Object obj)
     {

        if (obj == null)
        {
            return false;
        }
        if (getClass() != obj.getClass())
        {
            return false;
        }
        final Contact other = (Contact) obj;

        if (hashCode() != other.hashCode())
        {
            return false;
        }
        return true;
    }

    /**
     * Gera o hashcode do Contato a partir do nome e endereço.
     * @return Hashcode do Contato.
     */
    @Override
    public int hashCode()
    {
        int hash = 3;
        hash = 83 * hash + (this.name.toLowerCase() != null ? this.name.toLowerCase().hashCode() : 0);
        hash = 83 * hash + (this.address.toLowerCase() != null ? this.address.toLowerCase().hashCode() : 0);
        return hash;
    }

    /**
     * Informacoes do Contato num String.
     * @return String com as informacoes do Contato.
     */
    @Override
    public String toString()
    {
        String sEvents = "";
        for (Event e : events){
            sEvents += e.getName() + " | ";
        }
        DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
        return "Nome: " + name + "\nEndereço: " + address + "\nAniversário: "
                + df.format(dateOfBirth.getTime())  + "\nEventos: "
                + sEvents + "\nFormas de contato: " + contactWays + (comments != null ? "\nComentário: " + comments: "");
    }
}